package com.smap.control;

import java.util.ArrayList;
import java.util.List;

import com.smap.core.Map;
import com.smap.core.XY;
import com.smap.event.MapEvent;
import com.smap.layer.VectorLayer;
import com.smap.vector.Feature;
import com.smap.vector.LineString;
import com.smap.vector.Point;
import com.smap.vector.Polygon;
import com.smap.vector.Style;

public class VectorControl extends AbstractControl {
	/**
	 * 0 = select 1 = addPoint 2 = addLine 3 = addPolygon
	 */
	int mode = 0;
	Feature selectedFeat;
	Feature feat;
	VectorLayer layer;

	public VectorControl() {

	}

	public VectorControl(VectorLayer layer) {
		this.layer = layer;
	}

	public void onResize() {
		// TODO Auto-generated method stub

	}

	@Override
	void onEvent(MapEvent evt) {
		boolean redraw = false;
		if ("draging".equals(evt.type)) {
			// System.out.println(evt);
		} else if ("click".equals(evt.type)) {
			XY click = new XY(evt.x,evt.y);
			XY clickCoord = map.pixelToMap(click);
			if (mode == 0) {
				selectedFeat = layer.select(click);
				// todo, maybe need a unselected event
				map.fireEvent(new MapEvent(MapEvent.EVT_FEAT_SELECTED,
						selectedFeat));
				redraw = true;
			} else if (mode == 1) {// add point
				Feature feat = new Feature();
				feat.geom = new Point(clickCoord);
				layer.add(feat);
				map.fireEvent(new MapEvent(MapEvent.EVT_FEAT_ADDED, feat));
				redraw = true;
			} else if (mode == 2) {// add line
				if (feat == null){
					feat = new Feature();
					feat.geom = new LineString();
				}
				feat.geom.add(xy);

				feat.geom.add();
				redraw = true;
			} else if (mode == 3) {// add line
				Point p = new Point(evt.x, evt.y);
				helpPoints.add(p);
				redraw = true;
			}

		} else if ("dbclick".equals(evt.type)) {
			if (mode == 2) {// finish line
				Feature feat = new Feature();
				feat.screenGeom = new LineString(helpPoints);
				feat.reversePack(this.map);
				layer.add(feat);
				helpPoints.clear();
				evt.stop();
				redraw = true;
			} else if (mode == 3) {// finish polygon
				Feature feat = new Feature();
				feat.screenGeom = new Polygon(helpPoints);
				feat.reversePack(this.map);
				layer.add(feat);
				helpPoints.clear();
				evt.stop();
				redraw = true;
			}
		} else if (MapEvent.EVT_MAP_DRAWN.equals(evt.type)) {
			redraw = true;
		}
		if (redraw) {
			layer.draw();
			draw();
		}
	}

	private void draw() {
		if (selectedFeat != null) {
			Style style = selectedFeat.style.clone();
			style.stroke_width++;
			layer.draw(selectedFeat, style);
			style.label_color = "blue";
			layer.drawLabel(selectedFeat, style);
		}

		List<Point> pts = new ArrayList<Point>();
		Style helperStyle = new Style();
		helperStyle.fill_color = "green";
		helperStyle.line_width = 1;
		helperStyle.stroke_width = 1;
		helperStyle.point_radius = 4.0;
		Point lastP = null;

		for (Point pt : helpPoints) {
			layer.draw(pt, helperStyle);
			if (mode == 2 || mode == 3) {
				if (lastP != null) {
					pts.clear();
					pts.add(lastP);
					pts.add(pt);
					LineString line = new LineString(pts);
					layer.draw(line, helperStyle);
				}
				lastP = pt;
			}
		}
		if (mode == 3 && helpPoints.size() > 2) {
			pts.clear();
			pts.add(lastP);
			pts.add(helpPoints.get(0));
			LineString line = new LineString(pts);
			layer.draw(line, helperStyle);
		}
	}

	public void setLayer(VectorLayer layer) {
		this.layer = layer;
	}

	public void command(String cmd) {
		if ("select".equals(cmd)) {
			helpPoints.clear();
			mode = 0;
		} else if ("point".equals(cmd)) {
			helpPoints.clear();
			mode = 1;
		} else if ("line".equals(cmd)) {
			helpPoints.clear();
			mode = 2;
		} else if ("polygon".equals(cmd)) {
			helpPoints.clear();
			mode = 3;
		}
	}

	@Override
	public void install(Map map) {
		super.install(map);
		toolBar.addBtn("select", "s", true);
		toolBar.addBtn("point", ".", true);
		toolBar.addBtn("line", "\\", true);
		toolBar.addBtn("polygon", "D", true);

	}

}
